home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Tele / C / Comet2.1.3.cpt / Comet / gethost.c < prev    next >
Text File  |  1991-09-25  |  17KB  |  790 lines

  1. /*
  2.     Copyright Cornell University 1986.  All rights are reserved.
  3.     
  4.     gethost.c contains the dialog used to get a host name/address from 
  5.     the user and maintain the associated database.
  6.     
  7. */
  8.  
  9. #include <em.h>
  10.  
  11. #include <list.h>
  12.  
  13. #include <config.h>
  14.  
  15. #include <h19.h>
  16. #include <resdefs.h>
  17. #include <menudefs.h>
  18.  
  19. #include <net.h>            /* merged TCP */
  20. #ifdef DUALTCP
  21. #endif
  22.  
  23. #ifdef MACTCP
  24. #include <MacTCPCommonTypes.h>
  25. #include <AddressXlation.h>
  26.  
  27. #else
  28.  
  29. #include <tcp.h>
  30. #include <tcpdefs.h>
  31. #endif
  32.  
  33. extern char * malloc();
  34.  
  35. extern unsigned long mtdnresolve();
  36.  
  37. long nameresolved;
  38.  
  39. #define LASTHOSTID 0
  40.  
  41.  
  42. extern char * index();
  43.  
  44. /*  See permission and disclaimer notice in file "notice.h"  */
  45.  
  46.  
  47. /* resolve_name.c */
  48.  
  49. /* Resolve a host name into an internet address.  Three name formats are
  50.  * accepted:
  51.  *    1) A character string host name
  52.  *    2) An octal host number, in the form:
  53.  *        <net>,<subnet>,<rsd>,<host>
  54.  *        or a decimal host number, in the form:
  55.  *        <net>.<subnet>.<rsd>.<host>
  56.  *        Any of the <net>, <subnet>, and <rsd> may be left blank or left out
  57.  *        entirely; they default to the local net/subnet.
  58.  *    3) A thirty-two bit hex number, preceeded by a '#', which is used
  59.  *         without interpretation as the host number.
  60.  * If a character string name is supplied, it is first looked up in a
  61.  * local host table.  If it is not found there, the routine goes off to
  62.  * internet name servers to try to resolve the name.
  63.  *
  64.  * The following routines are included in this file:
  65.  *    resolve_name    Resolve a name as specified above
  66.  *    gethmch        Parse a hex machine address specification
  67.  *    getomch        Parse an octal machine address specification
  68.  * The routines which use the internet name server are in the file
  69.  * name_user.c.
  70.  */
  71.  
  72.  
  73. #define    INSZ    4
  74.  
  75. extern     char    *index();
  76.  
  77. /* Resolve foreign host internet address
  78.  * Scan table of host names and nicknames.
  79.  * For each name, see if our string is a prefix.  If so, keep checking -
  80.  * could be ambiguous.
  81.  * If ambiguous, return 0.
  82.  * When find no matches, try internet name servers.
  83.  *
  84.  * Arguments:
  85.  */
  86.  
  87. resolve_name(name, hsockp)
  88. char *name; 
  89. struct hostsock * hsockp;
  90. {
  91.     char tname[100];
  92.     char taddr[100];
  93.     unsigned int port;
  94.     int hostconnact;
  95.     int sockargs;
  96.     int dotargs;
  97.     short dotseen = FALSE;
  98.     unsigned char * namep;
  99.  
  100.     if (strlen(name) == 0) {
  101.         error("No address given");
  102.         return(-1);
  103.     }
  104.  
  105.     if ((name[0] >= '0') && (name[0] <= '9')) {
  106.         /* leading numeral indicates an internet address using dot notation */
  107.         if (getdmch(name, hsockp)) {
  108.             error(badaddress);
  109.             return(-1);
  110.         }
  111.     }
  112.     else if (name[0] == '#') {
  113.         /* leading '#' indicates hex address */
  114.         if (gethmch(name, hsockp)) {
  115.             error(badaddress);
  116.             return(-1);
  117.         }
  118.     }
  119.     else if (emdp->conntype == CONN_MACTCP) {
  120.         /* a string, hand it to the domain name resolver */
  121.         /* first parse the socket number which is "..300" format */
  122.         
  123.         hsockp->port = TELNETSOCK;
  124.         
  125.         sockargs = sscanf(name, "%s", &tname[0]);
  126.         dotargs = 0;
  127.         namep = &tname[0];
  128.         while (*namep) {
  129.             if (*namep == '.') {
  130.                 if (dotseen) {
  131.                     /* double dot is end of host name, beginning of socket */
  132.                     --namep;
  133.                     *namep = '\0';    /* terminate the string at first dot */
  134.                     namep += 2;            /* skip the dots */
  135.                     dotargs = sscanf(namep, "%d;%d", &port, &hostconnact); 
  136.                 }
  137.                 dotseen = TRUE;
  138.             }
  139.             else
  140.                 dotseen = FALSE;
  141.             namep++;
  142.         }
  143.  
  144.         /* we presume this is an IP Domain Name if it doesn't match
  145.             any of the above constants, so we try the DNR */
  146.             
  147.         if ((hsockp->u.addr = mtdnresolve(&tname[0])) == 0)
  148.             return(-1);
  149.             
  150.         if (hsockp->u.addr == -1)
  151.             /* prevent attempts to open a session with the broadcast address -1 ... */
  152.             return(-1);
  153.  
  154.         /* now set the socket and id portions */
  155.         if (dotargs >= 1 && port != 0)
  156.             hsockp->port = port;
  157.         else
  158.             hsockp->port = TELNETSOCK;
  159.             
  160.         if (dotargs == 2)
  161.             hsockp->hostconnact = hostconnact;
  162.         else
  163.             hsockp->hostconnact = -1;
  164.     }
  165.     else {
  166.     /* old TCP can't handle DNR */
  167.         error("Cornell TCP can't resolve domain names");
  168.         hsockp->u.addr = -1L;
  169.         return(-1);
  170.     }
  171.     return(0);
  172. }
  173.  
  174.     
  175. /* Parse foreign host number input as hex string */
  176.  
  177. gethmch(name, hsockp)
  178. register char *name; 
  179. struct hostsock * hsockp;
  180. {
  181.     register char    *tmp;
  182.     register int    i;
  183.     union {
  184.         char    bytes[INSZ];
  185.         long    name;
  186.     } addr;
  187.     
  188.     tmp = &name[1];
  189.     for (i = 0; i < 8; i++) {
  190.         if ((*tmp >= '0') && (*tmp <= '9'))
  191.             *tmp++ -= '0';
  192.         else if ((*tmp >= 'A') && (*tmp <= 'Z'))
  193.             *tmp++ -= ('A' - 10);
  194.         else if ((*tmp >= 'a') && (*tmp <= 'z'))
  195.             *tmp++ -= ('a' - 10);
  196.         else {
  197.             hsockp->u.addr = -1L;
  198.             return(-1);
  199.         }
  200.     }
  201.  
  202.     if (*tmp != 0) {
  203.         hsockp->u.addr = -1L;
  204.         return(-1);
  205.     }
  206.  
  207.     tmp = &name[1];
  208.     for (i = 0; i < INSZ; i++)
  209.         addr.bytes[i] = ((*tmp++ << 4) + *tmp++);
  210.     hsockp->u.addr = addr.name;
  211.     return(0);
  212. }
  213.  
  214.  
  215. /* Parse foreign host number input as decimal string, placing host socket in hsockp */
  216.  
  217. getdmch(name, hsockp)
  218. char    *name;
  219. struct hostsock * hsockp;
  220. {
  221.     unsigned int addr[4];
  222.     unsigned int port;
  223.     int hostconnact;
  224.     register char thechar;
  225.     register char * tempp;
  226.     int sockargs;
  227.     int ipargs;
  228.     int count;
  229.     int addrb;    /* counter for accessing the bytes in the addr backwards */
  230.  
  231.     sockargs = 0;
  232.  
  233.     hsockp->u.addr = rnet->ip_addr;
  234.     hsockp->port = 0;
  235.     hsockp->hostconnact = 0;
  236.         /* reset hostsock struct */
  237.  
  238.     /*    if a ".." is in the string, a socket comes after it; 
  239.             interpret the socket as a decimal #
  240.         if a ';' occurs in the address, it indicates a string ID for connect
  241.             actions
  242.     */
  243.     ipargs = sscanf(name, "%d.%d.%d.%d", &addr[0], &addr[1], 
  244.         &addr[2], &addr[3]);
  245.  
  246.     for (count = ipargs, addrb = 3; --count >= 0; --addrb) {
  247.         /* spot bad addresses for 1-4 */
  248.         if (addr[count] < 0 || addr[count] > 256) {
  249.             hsockp->u.addr = -1L;
  250.             return(-1);
  251.         }
  252.         hsockp->u.bytes[addrb] = addr[count];
  253.     }
  254.     
  255.     /* we got the IP address, get the rest */
  256.     sockargs = sscanf(name, "%d.%d.%d.%d..%d;%d", &addr[0], &addr[1], 
  257.         &addr[2], &addr[3], &port, &hostconnact);
  258.  
  259.     /* now set the socket as desired */
  260.     if (sockargs >= 5 && port != 0)
  261.         hsockp->port = port;
  262.     else
  263.         hsockp->port = TELNETSOCK;
  264.         
  265.     if (sockargs == 6)
  266.         hsockp->hostconnact = hostconnact;
  267.     else
  268.         hsockp->hostconnact = -1;
  269.  
  270.     return(0);
  271. }
  272.  
  273.  
  274. #ifdef MACTCP
  275.  
  276.  
  277. extern unsigned long getmyA5();
  278. pascal void resolved();
  279.  
  280. unsigned long mtdnresolve(tname)
  281. char * tname;            /* hostname */
  282. {
  283.     struct hostInfo hostinfo;
  284.  
  285.     if (!macipopen) {
  286.         /* open the MacTCP driver if not open TODO this won't handle async */
  287.         if (macip_init())
  288.             return(-1);
  289.     }
  290.     /* open the DNR */
  291.     if (OpenResolver(NULL)) {
  292.         error("Can't open MacTCP Domain Name Resolver");
  293.         return(-1);
  294.     }
  295.     
  296.     /* call the DNR */
  297. /*
  298.     char * mtcpresolvewait = "\r\r  Getting host address from domain name server...";
  299.     
  300.     fillwindow(COPYWINDOW, mtcpresolvewait, (long) strlen(mtcpresolvewait), systemFont, 12, (long) -1);
  301.  
  302.     for some reason this induces mactcp to crash!
  303. */
  304.     SetCursor(*GetCursor(watchCursor));
  305.         /* put up a watch cursor to show this may take some time */
  306.         
  307.     nameresolved = 0;
  308.     
  309.     StrToAddr(tname, &hostinfo, resolved, NULL);
  310.     while (!nameresolved) {
  311.         short thechar;
  312.         EventRecord evt;
  313.     
  314.         /* check to see if the user wants to abort, because mactcp's dnr 
  315.             sometimes hangs... */
  316.         GetNextEvent(keyDownMask|autoKeyMask, &evt);
  317.         if (evt.what == keyDown || evt.what == autoKey) {
  318.             thechar = evt.message & 0xff;
  319.             if (evt.modifiers & cmdKey) {
  320.                 if (thechar == '.') {
  321.                     error("Interrupting the MacTCP domain name resolver may be hazardous; you should probably reboot your machine");
  322.                     break;
  323.                 }
  324.             }
  325.         }
  326.         bkrd_service();
  327.     }
  328.  
  329.     SetCursor(&arrow);
  330.     
  331. /*
  332.     fillwindclose();
  333. */
  334.     CloseResolver();
  335.     if (nameresolved != 1) {
  336.         switch (nameresolved) {
  337.             case nameSyntaxErr:
  338.                 error("MacTCP resolver: invalid name syntax");
  339.                 break;
  340.             case cacheFault:
  341.                 error("MacTCP resolver: no answer from nameserver");
  342.                 /* error("MacTCP resolver: cache fault"); */
  343.                 break;
  344.             case noResultProc:
  345.                 error("MacTCP resolver: no result proc");
  346.                 break;
  347.             case noNameServer:
  348.                 error("MacTCP resolver: can't find name server");
  349.                 break;
  350.             case authNameErr:
  351.                 error("MacTCP resolver: auth. name error");
  352.                 break;
  353.             case noAnsErr:
  354.                 error("MacTCP resolver: no answer from nameserver");
  355.                 break;
  356.             case dnrErr:
  357.                 error("MacTCP resolver: error in domain name resolver");
  358.                 break;
  359.         }
  360.     }
  361.     return(hostinfo.addr[0]);
  362. }
  363.  
  364.  
  365. /*     DNR.c - DNR library for MPW
  366.  
  367.     (c) Copyright 1988 by Apple Computer.  All rights reserved
  368.     
  369. */
  370.  
  371.  
  372. #include <errors.h>
  373.  
  374. #define OPENRESOLVER    1
  375. #define CLOSERESOLVER    2
  376. #define STRTOADDR        3
  377. #define    ADDRTOSTR        4
  378. #define    ENUMCACHE        5
  379. #define ADDRTONAME        6
  380. #define    HINFO            7
  381. #define MXINFO            8
  382.  
  383. Handle codeHndl = NULL;
  384.  
  385. OSErrProcPtr dnr = NULL;
  386.  
  387. #define OLDDNR
  388. #ifdef OLDDNR
  389.  
  390. /* OpenOurRF is called to open the MacTCP driver resources */
  391.  
  392. short OpenOurRF()
  393. {
  394.     HPrmBlkRec fi;
  395.     Str255 filename;
  396. #define ZBEN
  397. #ifdef    ZBEN                /*    !    */
  398.     short    savevol;        /*    !    */
  399.     OSErr    status;            /*    !    */
  400.     extern SysEnvRec        environs;
  401. #endif                        /*    !    */
  402.  
  403.     fi.ioCompletion = NULL;
  404.     fi.ioNamePtr = &filename;
  405.     fi.ioVRefNum = environs.sysVRefNum;
  406.     fi.u.hfp.ioDirID = 0;
  407.     fi.u.hfp.ioFDirIndex = 1;
  408.     
  409.     while (PBHGetFInfo(&fi, (Boolean) FALSE) == noErr) {
  410.         /* scan system folder for driver resource files of specific type & creator */
  411.         if (fi.u.hfp.ioFlFndrInfo.fdType == 'cdev' &&
  412.             fi.u.hfp.ioFlFndrInfo.fdCreator == 'mtcp') {
  413.             /* found the MacTCP driver file */
  414. #ifdef    ZBEN                    
  415.                 /* a fix courtesy of usenet to the DNR,
  416.                     which will fail to get the resource it wants
  417.                     if it's not on the main Volume (another PMSP-related
  418.                     problem
  419.                 */
  420.                 
  421.                 /*    !    */
  422.             GetVol((StringPtr) NULL,&savevol);                    /*    !    */
  423.             SetVol((StringPtr) NULL,environs.sysVRefNum);            /*    !    */
  424.             status    =    OpenResFile(&filename);                    /*    !    */
  425.             SetVol((StringPtr) NULL,savevol);                    /*    !    */
  426.             return(status);                                        /*    !    */
  427. #else                                                            /*    !    */
  428.             return(OpenResFile(&filename));
  429. #endif
  430.         }
  431.         /* check next file in system folder */
  432.         fi.u.hfp.ioFDirIndex++;
  433.         fi.u.hfp.ioDirID = 0;
  434.     }
  435.     return(-1);
  436. }    
  437.  
  438.  
  439. OSErr OpenResolver(fileName)
  440. char *fileName;
  441. {
  442.     short refnum;
  443.     OSErr rc;
  444.     
  445.     if (dnr != NULL)
  446.         /* resolver already loaded in */
  447.         return(noErr);
  448.         
  449.     /* open the MacTCP driver to get DNR resources. Search for it based on
  450.        creator & type rather than simply file name */    
  451.     refnum = OpenOurRF();
  452.  
  453.     /* ignore failures since the resource may have been installed in the 
  454.        System file if running on a Mac 512Ke */
  455.        
  456.     /* load in the DNR resource package */
  457.     codeHndl = GetIndResource('dnrp', 1);
  458.     if (codeHndl == NULL) {
  459.         /* can't open DNR */
  460.         return(ResError());
  461.     }
  462.     
  463.     DetachResource(codeHndl);
  464.     if (refnum != -1) {
  465.         CloseResFile(refnum);
  466.     }
  467.         
  468.     /* lock the DNR resource since it cannot be reloated while opened */
  469.     HLock(codeHndl);
  470.     dnr = (OSErrProcPtr) *codeHndl;
  471.     
  472.     /* call open resolver */
  473.     rc = (*dnr)((long) OPENRESOLVER, fileName);
  474.     if (rc != noErr) {
  475.         /* problem with open resolver, flush it */
  476.         HUnlock(codeHndl);
  477.         DisposHandle(codeHndl);
  478.         dnr = NULL;
  479.     }
  480.     return(rc);
  481. }
  482.  
  483. #else
  484. /* use the stuff provided with MacTCP 1.1B1, which adds Sys 7.0-stuff */
  485.  
  486. TrapType GetTrapType(theTrap)
  487. unsigned long theTrap;
  488. {
  489.     if (BitAnd(theTrap, 0x0800) > 0)
  490.         return(ToolTrap);
  491.     else
  492.         return(OSTrap);
  493. }
  494.     
  495.     
  496.     
  497. Boolean TrapAvailable(trap)
  498. unsigned long trap;
  499. {
  500. TrapType trapType = ToolTrap;
  501. unsigned long numToolBoxTraps;
  502.  
  503.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  504.         numToolBoxTraps = 0x200;
  505.     else
  506.         numToolBoxTraps = 0x400;
  507.  
  508.     trapType = GetTrapType(trap);
  509.     if (trapType == ToolTrap) {
  510.         trap = BitAnd(trap, 0x07FF);
  511.         if (trap >= numToolBoxTraps)
  512.             trap = _Unimplemented;
  513.     }
  514.     return(NGetTrapAddress(trap, trapType) != NGetTrapAddress(_Unimplemented, ToolTrap));
  515.  
  516. }
  517.  
  518. short GetCPanelFolder()
  519. {
  520.     short vRefNum = 0;
  521.     long dirID = 0;
  522.     SysEnvRec info;
  523.     Boolean hasFolderMgr = (Boolean) FALSE;
  524.     long feature;
  525.     short wdRef;
  526.     
  527.     if (TrapAvailable(_GestaltDispatch)) 
  528.         if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) 
  529.             hasFolderMgr = (Boolean) TRUE;
  530.     if (!hasFolderMgr) {
  531.         SysEnvirons(1, &info);
  532.         return(info.sysVRefNum);
  533.     }
  534.     else {
  535.         if (FindFolder(kOnSystemDisk, kControlPanelFolderType, kDontCreateFolder, &vRefNum, &dirID) != noErr) 
  536.             return(0);
  537.         if (OpenWD(vRefNum, dirID, 'dnrp', &wdRef) == noErr)
  538.             return(wdRef);
  539.         else
  540.             return(0);
  541.     }
  542. }
  543.  
  544. /* OpenOurRF is called to open the MacTCP driver resources */
  545.  
  546. short OpenOurRF()
  547. {
  548.     ParamBlockRec fi;
  549.     Str255 filename;
  550.     short vRefNum;
  551.     
  552.     vRefNum = GetCPanelFolder();
  553.     fi.fileParam.ioCompletion = NULL;
  554.     fi.fileParam.ioNamePtr = &filename;
  555.     fi.fileParam.ioVRefNum = vRefNum;
  556.     fi.fileParam.ioFDirIndex = 1;
  557.     
  558.     while (PBGetFInfo(&fi, (Boolean) FALSE) == noErr) {
  559.         /* scan system folder for driver resource files of specific type & creator */
  560.         if (fi.fileParam.ioFlFndrInfo.fdType == 'cdev' &&
  561.             fi.fileParam.ioFlFndrInfo.fdCreator == 'ztcp') {
  562.             /* found the MacTCP driver file */
  563.             return(OpenRFPerm(&filename, vRefNum, fsRdPerm));
  564.         }
  565.         /* check next file in system folder */
  566.         fi.fileParam.ioFDirIndex++;
  567.     }
  568.     return(-1);
  569. }    
  570.  
  571.  
  572. OSErr OpenResolver(fileName)
  573. char *fileName;
  574. {
  575.     short refnum;
  576.     OSErr rc;
  577.     
  578.     if (dnr != NULL)
  579.         /* resolver already loaded in */
  580.         return(noErr);
  581.         
  582.     /* open the MacTCP driver to get DNR resources. Search for it based on
  583.        creator & type rather than simply file name */    
  584.     refnum = OpenOurRF();
  585.  
  586.     /* ignore failures since the resource may have been installed in the 
  587.        System file if running on a Mac 512Ke */
  588.        
  589.     /* load in the DNR resource package */
  590.     codeHndl = GetIndResource('dnrp', 1);
  591.     if (codeHndl == NULL) {
  592.         /* can't open DNR */
  593.         return(ResError());
  594.         }
  595.     
  596.     DetachResource(codeHndl);
  597.     if (refnum != -1) {
  598.         CloseWD(refnum);
  599.         CloseResFile(refnum);
  600.     }
  601.         
  602.     /* lock the DNR resource since it cannot be reloated while opened */
  603.     HLock(codeHndl);
  604.     dnr = (OSErrProcPtr) *codeHndl;
  605.     
  606.     /* call open resolver */
  607.     rc = (*dnr)((long) OPENRESOLVER, fileName);
  608.     if (rc != noErr) {
  609.         /* problem with open resolver, flush it */
  610.         HUnlock(codeHndl);
  611.         DisposHandle(codeHndl);
  612.         dnr = NULL;
  613.     }
  614.     return(rc);
  615. }
  616.  
  617.  
  618. #endif
  619.  
  620.  
  621. OSErr CloseResolver()
  622. {
  623.     if (dnr == NULL)
  624.         /* resolver not loaded error */
  625.         return(notOpenErr);
  626.         
  627.     /* call close resolver */
  628.     (void) (*dnr)((long) CLOSERESOLVER);
  629.  
  630.     /* release the DNR resource package */
  631.     HUnlock(codeHndl);
  632.     DisposHandle(codeHndl);
  633.     dnr = NULL;
  634.     return(noErr);
  635. }
  636.  
  637. OSErr StrToAddr(hostName, rtnStruct, resultproc, userDataPtr)
  638. char *hostName;
  639. struct hostInfo *rtnStruct;
  640. long resultproc;
  641. char *userDataPtr;
  642. {
  643.     if (dnr == NULL)
  644.         /* resolver not loaded error */
  645.         return(notOpenErr);
  646.         
  647.     return((*dnr)((long) STRTOADDR, hostName, rtnStruct, resultproc, userDataPtr));
  648. }
  649.     
  650. OSErr AddrToStr(addr, addrStr)
  651. unsigned long addr;
  652. char *addrStr;                                    
  653. {
  654.     if (dnr == NULL)
  655.         /* resolver not loaded error */
  656.         return(notOpenErr);
  657.         
  658.     (*dnr)((long) ADDRTOSTR, addr, addrStr);
  659.     return(noErr);
  660. }
  661.     
  662. OSErr EnumCache(resultproc, userDataPtr)
  663. long resultproc;
  664. char *userDataPtr;
  665. {
  666.     if (dnr == NULL)
  667.         /* resolver not loaded error */
  668.         return(notOpenErr);
  669.         
  670.     return((*dnr)((long) ENUMCACHE, resultproc, userDataPtr));
  671. }
  672.     
  673.     
  674. OSErr AddrToName(addr, rtnStruct, resultproc, userDataPtr)
  675. unsigned long addr;
  676. struct hostInfo *rtnStruct;
  677. long resultproc;
  678. char *userDataPtr;                                    
  679. {
  680.     if (dnr == NULL)
  681.         /* resolver not loaded error */
  682.         return(notOpenErr);
  683.         
  684.     return((*dnr)((long) ADDRTONAME, addr, rtnStruct, resultproc, userDataPtr));
  685. }
  686.  
  687. OSErr HInfo(hostName, returnRecPtr, resultProc, userDataPtr)
  688. char *hostName;
  689. struct returnRec *returnRecPtr;
  690. long resultProc;
  691. char *userDataPtr;
  692. {
  693.     if (dnr == NULL)
  694.         /* resolver not loaded error */
  695.         return(notOpenErr);
  696.         
  697.     return((*dnr)((long) HINFO, hostName, returnRecPtr, resultProc, userDataPtr));
  698.  
  699. }
  700.     
  701. OSErr MXInfo(hostName, returnRecPtr, resultProc, userDataPtr)
  702. char *hostName;
  703. struct returnRec *returnRecPtr;
  704. long resultProc;
  705. char *userDataPtr;
  706. {
  707.     if (dnr == NULL)
  708.         /* resolver not loaded error */
  709.         return(notOpenErr);
  710.         
  711.     return((*dnr)((long) MXINFO, hostName, returnRecPtr, resultProc, userDataPtr));
  712.  
  713. }
  714.  
  715. pascal void resolved(hostinfo, userdata)
  716. struct hostInfo * hostinfo;
  717. char * userdata;
  718. {
  719.     unsigned long oldA5;
  720.     
  721.     oldA5 = getmyA5(); 
  722.     
  723.     nameresolved = hostinfo->rtnCode;
  724.     switch (hostinfo->rtnCode) {
  725.         case 0: {
  726.             /* OK, I presume */
  727.             nameresolved = 1;
  728.             setA5(oldA5);
  729.             return;
  730.         }
  731.         case cacheFault: {
  732.             /* address not in cache, wait for resolver */
  733.             setA5(oldA5);
  734.             return;
  735.         }
  736.     }
  737.     setA5(oldA5);
  738. }
  739. #endif
  740.  
  741.  
  742. /* save host address resource (a C string) in the current resource file */
  743.  
  744. savehostres(twp)
  745. struct winds * twp;
  746. {
  747.     long len;
  748.     Handle ohlasthost;
  749.     
  750.     if (twp->hlasthost == NULL)
  751.         return(-1);
  752.         
  753.     ohlasthost = twp->hlasthost;
  754.  
  755.     if ( (twp->hlasthost = Get1Resource('LHST', LASTHOSTID) ) != NULL) {
  756.         killhost(twp);
  757.     }
  758.     len = GetHandleSize(ohlasthost);
  759.     twp->hlasthost = NewHandle((long) len);
  760.     strcpy(*twp->hlasthost, *ohlasthost);
  761.  
  762.     DisposHandle(ohlasthost);
  763.  
  764.     AddResource(twp->hlasthost, 'LHST', LASTHOSTID, "\P");
  765.     if (ResError()) {
  766.         error("Can't save TCP/IP Address");
  767.         return(-1);
  768.     }
  769.     else {
  770.         UpdateResFile(HomeResFile(twp->hlasthost));
  771.         DetachResource(twp->hlasthost);
  772.     }
  773. }
  774.  
  775.  
  776. killhost(twp)
  777. struct winds * twp;
  778. {
  779.     int hhosthome;
  780.     
  781.     hhosthome = HomeResFile(twp->hlasthost);
  782.     RmveResource(twp->hlasthost);
  783.     if (ResError())
  784.         error("No host name resource kill");
  785.         
  786.     UpdateResFile(hhosthome);
  787.     DisposHandle(twp->hlasthost);
  788. }
  789.  
  790.